/*****************************************************************************************
   
   Copyright (c) Microsoft Corporation. All rights reserved.

   Use of this code sample is subject to the terms of the Microsoft
   Permissive License, a copy of which should always be distributed with
   this file.  You can also access a copy of this license agreement at:
   http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx

 ****************************************************************************************/

using System;

namespace GrooveCommands
{
	class GrooveReplaceFormsDesigns: CommandUtils.GrooveUtilBase
	{
		private string m_SourceSpaceURI;
		private string m_TargetSpaceURI;
		private bool m_Force;
		
		[STAThread]
		static void Main(string[] i_Arguments)
		{
			CommandUtils.UtilAppMain.RunApplication(new GrooveReplaceFormsDesigns(i_Arguments));
		}
	
		public GrooveReplaceFormsDesigns(string[] i_Arguments)
			: base (i_Arguments)
		{
			base.UsageMessage = "GrooveReplaceFormsDesigns[PARAMS...]";
			base.HelpMessage = 
				"GrooveReplaceFormsDesigns\r\n\t" + 
				"Replaces 3.x form design for all matching 3.x tools in a space\r\n" +
				"Parameters:\r\n\t" +
				"/SourceWorkspace=    The Web Services URI for the source Groove workspace\r\n\t" +
				"/TargetWorkspace=    The Web Services URI for the target Groove workspace\r\n\t" +
				"[/Force              Replace regardless of design-version\r\n\t" +
				"[/Account=           The Web Services URI for the Groove account]\r\n\t" +
				"[/Identity=          The Web Services URI for the Groove identity]\r\n\t" +
				"[/RequestKey=        Token used to communicate Groove host]\r\n\t" +
				"[/Host=              The remote Groove host name to issue commands to]\r\n\t" +
				"[/Port=              The remote Groove host port to issue commands to]\r\n\t" +
				"[/Timeout=           Timeout (in ms) for Web Services method execution]\r\n\t" +
				"[/X=                 Configuration file to use for parameter input]\r\n\t" +
				"[/V                  Verbose output\r\n\t" +
				"\r\n";
		}

		public override CheckResult CheckParameters()
		{
			CommandUtils.UtilBase.CheckResult CheckResult = base.CheckParameters();
			if (CheckResult != CommandUtils.UtilBase.CheckResult.Succeeded )
				return CheckResult;

			m_SourceSpaceURI = base.GetParameterValue("SourceWorkspace");
			if (System.String.IsNullOrEmpty(m_SourceSpaceURI))
			{
				base.DisplayUsage("You must specify a source workspace.");
				return CommandUtils.UtilBase.CheckResult.Failed;
			}

			m_TargetSpaceURI = base.GetParameterValue("TargetWorkspace");
			if (System.String.IsNullOrEmpty(m_TargetSpaceURI))
			{
				base.DisplayUsage("You must specify a target workspace.");
				return CommandUtils.UtilBase.CheckResult.Failed;
			}

			m_Force = base.GetParameterValueFlag( "Force" );

			return base.CheckUnusedParameters();
		}

		public override CommandUtils.UtilBase.CheckResult Run()
		{
			GrooveWebServicesV12Helpers.Space SourceSpace = null;
			GrooveWebServicesV12Helpers.Space TargetSpace = null;

			try
			{
				SourceSpace = base.Identity.OpenSpace(m_SourceSpaceURI);
			}
			catch (System.Exception Exception)
			{
				base.StandardError.WriteLine("Unable to open source space: " + Exception.Message);
				throw Exception;
			}

			try
			{
				TargetSpace = base.Identity.OpenSpace(m_TargetSpaceURI);
			}
			catch (System.Exception Exception)
			{
				base.StandardError.WriteLine("Unable to open target space: " + Exception.Message);
				throw Exception;
			}

			if( SourceSpace.URI == TargetSpace.URI )
			{
				throw new Exception( "Source and target spaces are the same." );
			}

			// Enumerate the forms tools in the source workspace
			// and build a list of their
			// - tool designname
			// - tool designversion
			// - tool URI

			string[] SupportedTypes = new string[] {GrooveWebServicesV12Helpers.Shared.GROOVE_FORMS_TOOL_SUPPORTED_TYPE};

			System.Collections.Hashtable dic = new System.Collections.Hashtable();

			GrooveWebServicesV12Helpers.Tool[] SourceTools = SourceSpace.GetToolsBySupportedTypes(SupportedTypes);
			foreach (GrooveWebServicesV12Helpers.Forms.FormsTool FormsTool in SourceTools)
			{
				ToolDesignInfo tdi = new ToolDesignInfo( FormsTool );
				string key = tdi.DesignName;
				if( key=="" )
				{
					string msg = String.Format( "Source workspace tool '{0}' has no designname and will be ignored.", tdi.DisplayName );
					base.StandardError.WriteLine( msg );
				}
				else
				{
					if( dic.ContainsKey( key ) )
					{
						string msg = String.Format( "Error: The source workspace contains more than one tool with designname '{0}'.", key );
						throw new Exception( msg );
					}
					dic.Add( key, tdi );
				}
			}

			// Enumerate the forms tools in the target workspace
			// and build a list of their
			// - tool designname
			// - tool designversion
			// - tool URI
			GrooveWebServicesV12Helpers.Tool[] TargetTools = TargetSpace.GetToolsBySupportedTypes(SupportedTypes);
			foreach (GrooveWebServicesV12Helpers.Forms.FormsTool FormsTool in TargetTools)
			{
				ToolDesignInfo tdi = new ToolDesignInfo( FormsTool );
				string key = tdi.DesignName;
				if( dic.ContainsKey( key ) )
				{
					// Found a source match for this designname
					ToolDesignInfo tdiSource = (ToolDesignInfo)dic[key];
					GrooveWebServicesV12Helpers.Forms.FormsTool SourceTool = tdiSource.Tool;

					// Check the design version is greater (otherwise do NOT replace design) (unless m_Force)
					bool ok = m_Force;
					if( !ok && tdiSource.DesignVersion != tdi.DesignVersion )
					{
						ok = true;
						string[] sourceVer = tdiSource.DesignVersion.Split('.');
						string[] targetVer = tdi.DesignVersion.Split('.');
						for( int j=0; j<sourceVer.Length; j++ )
						{
							int nSource = int.Parse( sourceVer[j] );
							int nTarget = 0;
							if( targetVer.Length >= j )
							{
								nTarget = int.Parse( targetVer[j] );
							}
							if( nTarget > nSource )
							{
								ok = false;
								break;
							}
						}
					}
					if( !ok )
					{
						base.StandardError.WriteLine("Did not replace design of tool '{0}' ({1}) version {2} with {3}", tdi.DisplayName, tdi.DesignName, tdi.DesignVersion, tdiSource.DesignVersion );
					}
					else
					{
						// Replace the design of this tool from the source
						string[] targetList = new string[1];
						targetList[0] = tdi.URI;

						string[] ReplacedFormsToolsURIs = null;
						try
						{
							ReplacedFormsToolsURIs = SourceTool.ReplaceDesign( targetList );
						}
						catch( Exception e )
						{
							base.StandardError.WriteLine("Unable to replace design of tool '{0}': {1}", tdi.DisplayName, e.Message );
							throw e;
						}
						if (ReplacedFormsToolsURIs.Length != targetList.Length)
						{
							base.StandardError.WriteLine("Failed to replace design of tool '{0}'", tdi.DisplayName );
						}
						else
						{
							base.StandardError.WriteLine("Replaced design of tool '{0}' ({1}) version {2} with {3}", tdi.DisplayName, tdi.DesignName, tdi.DesignVersion, tdiSource.DesignVersion );
						}
					}
				}
				else
				{
					string msg = String.Format( "Source workspace has no tools with designname '{0}'.  Tool '{1}' in target ignored.", key, tdi.DisplayName );
					base.StandardError.WriteLine( msg );
				}
			}

			return CommandUtils.UtilBase.CheckResult.Succeeded;
		}
	}

	class ToolDesignInfo
	{
		public GrooveWebServicesV12Helpers.Forms.FormsTool Tool;
		public string DisplayName;
		public string URI;
		public string DesignName;
		public string DesignVersion;
		public ToolDesignInfo( GrooveWebServicesV12Helpers.Forms.FormsTool FormsTool )
		{
			this.Tool = FormsTool;
			this.DisplayName = FormsTool.Name;
			this.URI = FormsTool.URI;

			GrooveWebServicesV12Helpers.Forms.ToolProperties ToolProperties = FormsTool.ToolProperties;
			this.DesignName = ToolProperties.DesignTemplateName;
			this.DesignVersion = ToolProperties.DesignTemplateVersion;
		}
	}
}